package com.wulwu.permission.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wulwu.permission.enums.ResultCode;
import com.wulwu.permission.model.UserEntity;
import com.wulwu.permission.utils.JwtUtils;
import com.wulwu.permission.utils.Result;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

/**
 * @Description Jwt自义定登录拦截器
 * @Author Major
 * @Date 2020/12/4 16:41
 */
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    public JWTLoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        //设置登录URL
        super.setFilterProcessesUrl("/auth/login");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //调用 UserDetailService 账号密码登录
        try {
            UserEntity userEntity = new ObjectMapper().readValue(request.getInputStream(), UserEntity.class);
            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(userEntity.getUsername(), userEntity.getPassword(), new ArrayList<>())
            );
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /*
     * @Description 账号密码验证成功
     * @Author Major
     * @Date 2020/12/4 16:47
     * @Param request:
     * @Param response:
     * @Param chain:
     * @Param authResult:
     * @Return void
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //账号验证通过,设置 header 中的 jwt
        UserEntity userEntity = (UserEntity) authResult.getPrincipal();
        String jwtToken = JwtUtils.generateJsonWebToken(userEntity);

        // 设置编码 防止乱码问题
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        // 在请求头里返回创建成功的token
        // 设置请求头为带有"Bearer "前缀的token字符串
        response.setHeader(JwtUtils.TOKEN_HEADER, JwtUtils.TOKEN_PREFIX + jwtToken);

        // 处理编码方式 防止中文乱码
        response.setContentType("text/json;charset=utf-8");
        // 将反馈塞到HttpServletResponse中返回给前台
        response.getWriter().write(JSON.toJSONString(new Result(ResultCode.LOGIN_SUCCESS)));
    }

    /*
     * @Description 账号密码验证失败
     * @Author Major
     * @Date 2020/12/4 16:47
     * @Param request:
     * @Param response:
     * @Param failed:
     * @Return void
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        String returnData = "";
        // 账号过期
        if (failed instanceof AccountExpiredException) {
            returnData = "账号过期--" + failed.getMessage();
        }
        else if (failed instanceof UsernameNotFoundException) {
            returnData = failed.getMessage();
        }
        // 密码错误
        else if (failed instanceof BadCredentialsException) {
            returnData = "密码错误--" + failed.getMessage();
        }
        // 密码过期
        else if (failed instanceof CredentialsExpiredException) {
            returnData = "密码过期--" + failed.getMessage();
        }
        // 账号不可用
        else if (failed instanceof DisabledException) {
            returnData = "账号不可用--" + failed.getMessage();
        }
        //账号锁定
        else if (failed instanceof LockedException) {
            returnData = "账号锁定--" + failed.getMessage();
        }
        // 用户不存在
        else if (failed instanceof InternalAuthenticationServiceException) {
            returnData = "用户不存在--" + failed.getMessage();
        }
        // 其他错误
        else {
            returnData = "未知异常--" + failed.getMessage();
        }

        // 处理编码方式 防止中文乱码
        response.setContentType("text/json;charset=utf-8");
        // 将反馈塞到HttpServletResponse中返回给前台
        response.getWriter().write(JSON.toJSONString(new Result
                (ResultCode.LOGIN_ERROR.getCode(),ResultCode.LOGIN_ERROR.getMsg() + "--" + returnData)));
    }
}
